#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8:

"""
@version: 1.0
@author: readerror
@contact: readerror@readerror.cn
@contact1: readerror000@gmail.com
@site: http://www.readerror.cn
@software: PyCharm
@file: network.py
@time: 2017/3/22 10:17
"""


class NetworkApiMixin(object):
    def api_call(self, api, data, async=False, period=60.0):
        NotImplementedError()

    def get_api_result(self, res, api_name=False):
        NotImplementedError()

    def query_l2_network(self, data=None, async=False):
        """
        QueryL2Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'conditions': [{'name': 'type', 'op': '=', 'value': 'L2NoVlanNetwork'}],
         'session': {'uuid': 'b0c42025c7aa40a8854e6f62e5ead653'}}
        """
        if data is None:
            data = {}
        if data.get('conditions') is None:
            data['conditions'] = []
        rsp = self.api_call("org.zstack.header.network.l2.APIQueryL2NetworkMsg", data, async=async)
        return self.get_api_result(rsp)

    def query_l2_vlan_network(self, data=None, async=False):
        if data is None:
            data = {}
        if data.get('conditions') is None:
            data['conditions'] = []
        rsp = self.api_call('org.zstack.header.network.l2.APIQueryL2VlanNetworkMsg', data, async=async)
        return self.get_api_result(rsp)

    def query_l3_network(self, data=None, async=False):
        """
        QueryL3Network
        :param data:
        :param async: Can be used to asynchronously execute code.
        {'conditions': [], 'session': {'uuid': 'a4d7f1e5cc1f4f72b147205c461dd8c6'}}
        """
        if data is None:
            data = {}
        if data.get('conditions') is None:
            data['conditions'] = []
        rsp = self.api_call('org.zstack.header.network.l3.APIQueryL3NetworkMsg', data, async=async)
        return self.get_api_result(rsp)

    def create_l2_vlan_network(self, data, async=False):
        """
        CreateL2VlanNetwork
        :param async: Can be used to asynchronously execute code.
        :param data: {
            "physicalInterface": "enp3s0",
            "zoneUuid": "311d4076242043819132a0e21a03ef10",
            "name": "testnetwork1",
            "vlan": "106", "type": "L2VlanNetwork"
            }
        """
        rsp = self.api_call('org.zstack.header.network.l2.APICreateL2VlanNetworkMsg', data, async=async, period=0.2)
        return self.get_api_result(rsp)

    def create_l3_network(self, data, async=False):
        """
        CreateL3Network
        :param async: Can be used to asynchronously execute code.
        :param data:{
            "name": "yun3",
            "type": "L3BasicNetwork",
            "l2NetworkUuid": "97acd3262ad3419da4d3d9f2e90e6fef",
            "system": false,
            "count": false,
            "start": 0,
            "replyWithCount": true,
            "conditions": [],
        }
        """
        rsp = self.api_call('org.zstack.header.network.l3.APICreateL3NetworkMsg', data, async=async, period=0.1)
        return self.get_api_result(rsp)

    def add_dns_to_l3_network(self, data, async=False):
        """
        AddDnsToL3Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'dns': '8.8.8.8',
         'l3NetworkUuid': 'b7e7b79ce1174b8eb9bea2b249bd5d0a',
         'session': {'callid': 'api-kDs0byzX',
                     'uuid': 'f2393fbf099945d6992864b72b579462'}}
        """
        rsp = self.api_call('org.zstack.header.network.l3.APIAddDnsToL3NetworkMsg', data, async=async, period=0.1)
        return self.get_api_result(rsp)

    def query_network_service_provider(self, data, async=False):
        """
        QueryNetworkServiceProvider
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'conditions': [],
         'count': False,
         'replyWithCount': True,
         'session': {'callid': 'api-MLwWABMd',
                     'uuid': 'f2393fbf099945d6992864b72b579462'},
         'start': 0}
        """
        if data.get('conditions') is None:
            data['conditions'] = []
        rsp = self.api_call('org.zstack.header.network.service.APIQueryNetworkServiceProviderMsg', data, async=async)
        return self.get_api_result(rsp)

    def attach_network_service_to_l3_network(self, data, async=False):
        """
        AttachNetworkServiceToL3Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'l3NetworkUuid': 'b7e7b79ce1174b8eb9bea2b249bd5d0a',
         'networkServices': {'5982daf72ca149c2bd97123e10740154': ['SecurityGroup'],
                             '8562599dcaf54a618049ddb6ff2893bd': ['DNS',
                                                                  'SNAT',
                                                                  'LoadBalancer',
                                                                  'PortForwarding',
                                                                  'Eip',
                                                                  'DHCP',
                                                                  'IPsec']},
         'session': {'callid': 'api-hydRbL5X',
                     'uuid': 'f2393fbf099945d6992864b72b579462'}}
        """
        rsp = self.api_call(
            'org.zstack.header.network.service.APIAttachNetworkServiceToL3NetworkMsg', data, async=async, period=0.1)
        return self.get_api_result(rsp)

    def add_ip_range_by_network_cidr(self, data, async=False):
        """
        AddIpRangeByNetworkCidr
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'l3NetworkUuid': 'b7e7b79ce1174b8eb9bea2b249bd5d0a',
         'name': '150.150.150.0/24',
         'networkCidr': '150.150.150.0/24',
         'session': {'callid': 'api-qMZFd8IO',
                     'uuid': 'f2393fbf099945d6992864b72b579462'}}
        """
        rsp = self.api_call(
            'org.zstack.header.network.l3.APIAddIpRangeByNetworkCidrMsg', data, async=async, period=0.1
        )
        return self.get_api_result(rsp)

    def attach_l2_network_to_cluster(self, data, async=False):
        """
        AttachL2NetworkToCluster
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'clusterUuid': '1ee8ae0dfbe943afa07561dee8be26ab',
         'l2NetworkUuid': '182d33cbceee4157a1096ab32fd09ad0',
         'session': {'callid': 'api-fUNRMe1n',
                     'uuid': 'f2393fbf099945d6992864b72b579462'}}
        """
        rsp = self.api_call(
            'org.zstack.header.network.l2.APIAttachL2NetworkToClusterMsg', data, async=async, period=0.1
        )
        return self.get_api_result(rsp)

    def create_vip(self, data, async=False):
        """
        CreateVip
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'l3NetworkUuid': 'c88169cc00864306b00becf33b9d7f20',
         'name': 'vip-486276b7-c972-4009-2f0f-879e3744390c',
         'requiredIp': None}
        """
        rsp = self.api_call('org.zstack.network.service.vip.APICreateVipMsg', data, async=async)
        return self.get_api_result(rsp)

    def create_eip(self, data, async=False):
        """
        CreateEip
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'description': '',
         'name': 'xxxhhh',
         'vipUuid': 'b9819c0f1a844d4689e9d6b56040bd4d'}
        """
        rsp = self.api_call('org.zstack.network.service.eip.APICreateEipMsg', data, async=async)
        return self.get_api_result(rsp)

    def attach_eip(self, data, async=False):
        """
        AttachEip
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'eipUuid': '85c03eda7ec84c11817b15a6de768eee',
         'vmNicUuid': '94818505158e46319da06e508dd5e086'}
        """
        rsp = self.api_call('org.zstack.network.service.eip.APIAttachEipMsg', data, async=async)
        return self.get_api_result(rsp)

    def create_virtual_router_offering(self, data, async=False):
        """
        CreateVirtualRouterOffering
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'cpuNum': 1,
         'cpuSpeed': 1,
         'description': '',
         'imageUuid': '4e1069d515b24ee29c4effe2b8f4feae',
         'isDefault': True,
         'managementNetworkUuid': 'c88169cc00864306b00becf33b9d7f20',
         'memorySize': 1073741824,
         'name': '12343434',
         'publicNetworkUuid': 'c88169cc00864306b00becf33b9d7f20',
         'systemTags': ['vrouter'],
         'zoneUuid': '311d4076242043819132a0e21a03ef10'}
        """
        rsp = self.api_call('org.zstack.network.service.virtualrouter.APICreateVirtualRouterOfferingMsg', data,
                            async=async)
        return self.get_api_result(rsp)

    def query_security_group(self, data=None, async=False):
        """
        QuerySecurityGroup
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'conditions': [{'name': 'uuid',
                         'op': '=',
                         'value': 'a36ba4b3a7c946e8af7dba4291bc0f9a'}],
         'session': {'uuid': '81c41f1e3fd24a09ae648b0fade33aa5'}}
        """
        if data is None:
            data = {}
        if data.get('conditions') is None:
            data['conditions'] = []
        rsp = self.api_call("org.zstack.network.securitygroup.APIQuerySecurityGroupMsg", data, async=async)
        return self.get_api_result(rsp)

    def create_security_group(self, data, async=False):
        """
        CreateSecurityGroup
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'description': 'test\xe7\xae\x80\xe4\xbb\x8b',
         'name': 'test',
         'session': {'callid': 'api-FAq3qVCs',
                     'uuid': '1a9ce40db2454ac389e85f6ffb4ace20'}}
        """
        rsp = self.api_call("org.zstack.network.securitygroup.APICreateSecurityGroupMsg", data, async=async)
        return self.get_api_result(rsp)

    def delete_security_group(self, data, async=False):
        """
        DeleteSecurityGroup
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'session': {'callid': 'api-zdj2CoI0',
                     'uuid': 'b8ffd6374e134532897a44ea5eb19d45'},
         'uuid': 'a36ba4b3a7c946e8af7dba4291bc0f9a'}
        """
        rsp = self.api_call("org.zstack.network.securitygroup.APIDeleteSecurityGroupMsg", data, async=async)
        return self.get_api_result(rsp)

    def add_security_group_rule(self, data, async=False):
        """
        AddSecurityGroupRule
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'rules': [{'endPort': 80,
                    'protocol': 'TCP',
                    'startPort': 80,
                    'type': 'Ingress'}],
         'securityGroupUuid': '049049a29c3c4de9b0f919c9c9d82add',
         'session': {'callid': 'api-9DP4bytr',
                     'uuid': '1a9ce40db2454ac389e85f6ffb4ace20'}}
        """
        rsp = self.api_call("org.zstack.network.securitygroup.APIAddSecurityGroupRuleMsg", data, async=async)
        return self.get_api_result(rsp)

    def delete_security_group_rule(self, data, async=False):
        """
        DeleteSecurityGroupRule
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'ruleUuids': ['123456'],
         'session': {'uuid': 'd11f1405b35248a7bc0886a60a61e2d2'}}
        """
        rsp = self.api_call("org.zstack.network.securitygroup.APIDeleteSecurityGroupRuleMsg", data, async=async)
        return self.get_api_result(rsp)

    def attach_security_group_to_l3_network(self, data, async=False):
        """
        AttachSecurityGroupToL3Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'l3NetworkUuid': 'f7449be2739b461398bdc8c5530e1603',
         'securityGroupUuid': '049049a29c3c4de9b0f919c9c9d82add',
         'session': {'callid': 'api-UgKkVDwY',
                     'uuid': '1a9ce40db2454ac389e85f6ffb4ace20'}}
        """
        rsp = self.api_call("org.zstack.network.securitygroup.APIAttachSecurityGroupToL3NetworkMsg", data, async=async)
        return self.get_api_result(rsp)

    def detach_security_group_from_l3_network(self, data, async=False):
        """
        DetachSecurityGroupFromL3Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'l3NetworkUuid': '12345',
         'securityGroupUuid': '12345678',
         'session': {'uuid': 'd11f1405b35248a7bc0886a60a61e2d2'}}
        """
        rsp = self.api_call("org.zstack.network.securitygroup.APIDetachSecurityGroupFromL3NetworkMsg", data,
                            async=async)
        return self.get_api_result(rsp)

    def delete_l2_network(self, data, async=False):
        """
        DeleteL2Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'uuid': 'ccd0c65e780c4fa6962a792b920b6b3b'}
        """
        rsp = self.api_call("org.zstack.header.network.l2.APIDeleteL2NetworkMsg", data, async=async)
        return self.get_api_result(rsp)

    def delete_l3_network(self, data, async=False):
        """
        DeleteL3Network
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'session': {'uuid': '50dd7b1a48f04af398dbcf9d0749cdd7'},
         'uuid': 'd8aac753e8ec441694111b0e15008691'}
        """
        rsp = self.api_call("org.zstack.header.network.l3.APIDeleteL3NetworkMsg", data, async=async)
        return self.get_api_result(rsp)

    def delete_eip(self, data, async=False):
        """
        DeleteEip
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'session': {'callid': 'api-hgRSEyIS',
                     'uuid': '476f8a4431db4d8cab7d21249f6017b1'},
         'uuid': '72cf0693913a457a9a13ec232cf08e5c'}
        """
        rsp = self.api_call("org.zstack.network.service.eip.APIDeleteEipMsg", data, async=async)
        return self.get_api_result(rsp)

    def query_eip(self, data=None, async=False):
        """
        QueryEip
        :param async: Can be used to asynchronously execute code.
        :param data:
        {'conditions': [], 'session': {'uuid': 'f65ac744640744a49d8b78f0e7364641'}}
        """
        if data is None:
            data = {}
        if data.get('conditions') is None:
            data['conditions'] = []
        rsp = self.api_call("org.zstack.network.service.eip.APIQueryEipMsg", data, async=async)
        return self.get_api_result(rsp)
